package com.captain.leetcode;

/**
 * Des:
 * 实现获取 下一个排列 的函数，算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
 * <p>
 * 如果不存在下一个更大的排列，则将数字重新排列成最小的排列（即升序排列）。
 * <p>
 * 必须 原地 修改，只允许使用额外常数空间。
 * <p>
 *  
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [1,2,3]
 * 输出：[1,3,2]
 * 示例 2：
 * <p>
 * 输入：nums = [3,2,1]
 * 输出：[1,2,3]
 * 示例 3：
 * <p>
 * 输入：nums = [1,1,5]
 * 输出：[1,5,1]
 * 示例 4：
 * <p>
 * 输入：nums = [1]
 * 输出：[1]
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/next-permutation
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * @author XL
 * @Date 2021/7/17 0:09
 */
public class 下一个排列31 {

    public static void main(String[] args) {
        int[] arr = new int[]{1, 2, 1};
        nextPermutation(arr);
        for (int i : arr) {
            System.out.println(i);
        }
    }

    public static void nextPermutation(int[] nums) {
        if (nums == null || nums.length == 0) return;
        int j = nums.length - 1;
        while (j > 0) {
            //从后往前遍历
            if (nums[j] <= nums[j - 1]) {
                j--;
                if (j == 0) {
                    reverse(nums, 0);
                }
            } else {
                //找到位置
                int start = j - 1;
                while (j < nums.length && nums[j] > nums[start]) {
                    j++;
                }
                //找到交换的位置
                j--;
                int temp = nums[start];
                nums[start] = nums[j];
                nums[j] = temp;
                //将后面的数字进行
                reverse(nums, start + 1);
                return;
            }
        }
    }

    private static void reverse(int[] nums, int index) {
        int i = index;
        int j = nums.length - 1;
        while (i < j) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            i++;
            j--;
        }
    }
}
